package com.xbongbong.saas.help.workflow;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.PaasFormDataEntity;
import com.xbongbong.paas.elasticsearch.util.EsHelper;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.IndexTypeEnum;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.util.ExplainUtil;
import com.xbongbong.pro.domain.entity.UpdateDataEntity;
import com.xbongbong.saas.constant.ParameterConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.entity.SupplierProductEntity;
import com.xbongbong.saas.enums.SelectProductEnum;
import com.xbongbong.saas.enums.business.ProductEnum;
import com.xbongbong.saas.enums.product.SupplierProductEnum;
import com.xbongbong.saas.model.ProductModel;
import com.xbongbong.saas.model.SupplierProductModel;
import com.xbongbong.saas.toolbox.help.FastJsonHelper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
import static org.elasticsearch.index.query.QueryBuilders.termQuery;
import static org.elasticsearch.index.query.QueryBuilders.termsQuery;

/**
 *
 * @author 魏荣杰
 *
 */
@Component
@Slf4j
public class SupplierHelp {

    @Resource
    private SupplierProductModel supplierProductModel;
    @Resource
    private EsHelper esHelper;
    @Resource
    private ProductModel productModel;


    /**
     * 保存供应商产品
     * @param corpid 公司Id
     * @param supplierId 供应商ID
     * @param supplierName
     * @param productArray 产品Id
     * @throws XbbException 异常
     */
    public void saveSupplierProduct(boolean isNew, String corpid, Long supplierId, String supplierName, JSONArray productArray) throws XbbException {
        if (productArray == null) {
            productArray = new JSONArray();
        }
        if (isNew && productArray.isEmpty()) {
            return;
        }
        HashMap<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put(ParameterConstant.CORPID, corpid);
        param.put("supplierId", supplierId);
        param.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
        List<SupplierProductEntity> supplierProducts = supplierProductModel.findEntitys(param);

        Set<Long> newProductIds = new HashSet<>();
        Set<Long> oriProductIds = new HashSet<>();
        Set<Long> sameProductIds = new HashSet<>();
        Map<Long, String> unitMap = new HashMap<>();
        for (int i = 0; i < productArray.size();i++) {
            JSONObject jsonObject = productArray.getJSONObject(i);
            Long productId = jsonObject.getLong(SelectProductEnum.PRODUCT.getAttr());
            newProductIds.add(productId);
            if (Objects.nonNull(jsonObject.get(ProductEnum.UNIT.getAttr()))) {
                unitMap.put(productId, jsonObject.get(ProductEnum.UNIT.getAttr()).toString());
            }
        }
        Map<Long, SupplierProductEntity> supplierProductMap = new HashMap<>(supplierProducts.size());
        for (SupplierProductEntity supplierProduct : supplierProducts) {
            oriProductIds.add(supplierProduct.getProductId());
            sameProductIds.add(supplierProduct.getProductId());
            supplierProductMap.put(supplierProduct.getProductId(), supplierProduct);
        }
        // 编辑的数据
        sameProductIds.retainAll(newProductIds);
        // 删除的数据
        oriProductIds.removeAll(sameProductIds);
        // 新增的数据
        newProductIds.removeAll(sameProductIds);

        Set<Long> newAndDelProductIds = new HashSet<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        newAndDelProductIds.addAll(newProductIds);
        newAndDelProductIds.addAll(oriProductIds);
        BoolQueryBuilder boolQueryBuilder = boolQuery();
        boolQueryBuilder.filter(termQuery("corpid.keyword", corpid));
        boolQueryBuilder.filter(termsQuery(StringConstant.DATA_ID, newAndDelProductIds));
        List<String> fieldList = new ArrayList<>();
        fieldList.add(StringConstant.SAAS_LINK_BUSINESS_ID);
        fieldList.add(ProductEnum.getAttrConnectData(ProductEnum.PARENT_ID));
        fieldList.add(ProductEnum.getAttrConnectData(ProductEnum.UNIT));
        fieldList.add(ProductEnum.getAttrConnectData(ProductEnum.SUPPLIER));
        fieldList.add(ProductEnum.getAttrConnectData(ProductEnum.SUPPLIER_LINK_TEXT));
        List<PaasFormDataEntity> productList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_PRODUCT, boolQueryBuilder, PaasFormDataEntity.class, fieldList);
        Map<Long, PaasFormDataEntity> productMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Set<Long> parentProductIdSet = new HashSet<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        productList.forEach(product -> {
            productMap.put(product.getId(), product);
            parentProductIdSet.add(product.getData().getLong(ProductEnum.PARENT_ID.getAttr()));
        });
        boolQueryBuilder = boolQuery();
        boolQueryBuilder.filter(termQuery("corpid.keyword", corpid));
        boolQueryBuilder.filter(termsQuery(StringConstant.DATA_ID, parentProductIdSet));
        List<PaasFormDataEntity> parentProductList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_PRODUCT, boolQueryBuilder, PaasFormDataEntity.class, fieldList);
        Map<Long, PaasFormDataEntity> parentProductMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        parentProductList.forEach(paasFormDataEntity -> parentProductMap.put(paasFormDataEntity.getId(), paasFormDataEntity));
        List<Long> deleteBatchList = new ArrayList<>();
        for (Long delId : oriProductIds) {
            if (supplierProductMap.containsKey(delId)) {
                SupplierProductEntity delEntity = supplierProductMap.get(delId);
                deleteBatchList.add(delEntity.getId());
            }
        }
        if (!deleteBatchList.isEmpty()) {
            supplierProductModel.deleteByKeys(deleteBatchList, corpid);
        }

        List<SupplierProductEntity> addBatchList = new ArrayList<>();
        List<SupplierProductEntity> updateBatchList = new ArrayList<>();
        Integer sort = supplierProducts.size();
        SupplierProductEntity supplierProductEntity;
        for (int i = 0;i < productArray.size();i++) {
            JSONObject jsonObject = productArray.getJSONObject(i);
            Long productId = jsonObject.getLong(SelectProductEnum.PRODUCT.getAttr());
            if (newProductIds.contains(productId)) {
                PaasFormDataEntity paasFormDataEntity = productMap.get(productId);
                supplierProductEntity = new SupplierProductEntity(corpid, supplierId, supplierName, paasFormDataEntity.getData().getLong(ProductEnum.PARENT_ID.getAttr()), productId, sort);
                supplierProductEntity.setUnit(unitMap.get(productId));
                if (Objects.nonNull(unitMap.get(productId))) {
                    jsonObject.put(SupplierProductEnum.UNIT.getAttr(), unitMap.get(productId));
                }
                supplierProductEntity.setData(jsonObject);
                addBatchList.add(supplierProductEntity);
                sort++;
            }
            if (sameProductIds.contains(productId)) {
                SupplierProductEntity sameProductEntity = supplierProductMap.get(productId);
                sameProductEntity.setSupplierName(supplierName);
                if (Objects.nonNull(sameProductEntity)) {
                    sameProductEntity.setData(jsonObject);
                    sameProductEntity.setSort(sort);
                    updateBatchList.add(sameProductEntity);
                }
                sort++;
            }
        }
        if (!addBatchList.isEmpty()) {
            supplierProductModel.batchInsert(addBatchList);
        }
        if (!updateBatchList.isEmpty()) {
            supplierProductModel.updateBatch(updateBatchList, corpid);
        }
        // 更新产品表里的关联供应商字段
        List<UpdateDataEntity> updateDataEntityList = new ArrayList<>();
        for (PaasFormDataEntity paasFormDataEntity : productList) {
            PaasFormDataEntity parentProduct = parentProductMap.get(paasFormDataEntity.getData().getLong(ProductEnum.PARENT_ID.getAttr()));
            List<String> supplierIdArr = FastJsonHelper.getJsonArrOrDefaultFromFormData(paasFormDataEntity.getData(), ProductEnum.SUPPLIER.getAttr(), new JSONArray()).toJavaList(String.class);
            List<String> supplierNameArr = FastJsonHelper.getJsonArrOrDefaultFromFormData(paasFormDataEntity.getData(), ProductEnum.SUPPLIER_LINK_TEXT.getAttr(), new JSONArray()).toJavaList(String.class);
            List<String> parentSupplierIdArr = null;
            List<String> parentSupplierNameArr = null;
            if (Objects.nonNull(parentProduct)) {
                parentSupplierIdArr = FastJsonHelper.getJsonArrOrDefaultFromFormData(parentProduct.getData(), ProductEnum.SUPPLIER.getAttr(), new JSONArray()).toJavaList(String.class);
                parentSupplierNameArr = FastJsonHelper.getJsonArrOrDefaultFromFormData(parentProduct.getData(), ProductEnum.SUPPLIER_LINK_TEXT.getAttr(), new JSONArray()).toJavaList(String.class);
            }
            if (newProductIds.contains(paasFormDataEntity.getId())) {
                setProductSupplier(corpid, supplierId, supplierName, updateDataEntityList, paasFormDataEntity, supplierIdArr, supplierNameArr);
                if (Objects.nonNull(parentProduct)) {
                    setProductSupplier(corpid, supplierId, supplierName, updateDataEntityList, parentProduct, parentSupplierIdArr, parentSupplierNameArr);
                }
            } else if (oriProductIds.contains(paasFormDataEntity.getId())) {
                removeProductSupplier(corpid, supplierId, supplierName, updateDataEntityList, paasFormDataEntity, supplierIdArr, supplierNameArr);
            }
        }
        if (CollectionUtils.isNotEmpty(updateDataEntityList)) {
            productModel.updateBatch(updateDataEntityList, corpid);
        }
    }


    private void setProductSupplier(String corpid, Long supplierId, String supplierName, List<UpdateDataEntity> updateDataEntityList, PaasFormDataEntity paasFormDataEntity, List<String> supplierIdArr, List<String> supplierNameArr) {
        if (Objects.nonNull(supplierIdArr) && !supplierIdArr.contains(supplierId.toString())) {
            supplierIdArr.add(supplierId.toString());
            supplierNameArr.add(supplierName);
            JSONObject data = new JSONObject();
            data.put(ProductEnum.SUPPLIER.getAttr(), supplierIdArr);
            data.put(ProductEnum.SUPPLIER_LINK_TEXT.getAttr(), supplierNameArr);
            updateDataEntityList.add(ExplainUtil.getUpdateData(paasFormDataEntity.getId(), data, corpid));
        }
    }

    private void removeProductSupplier(String corpid, Long supplierId, String supplierName, List<UpdateDataEntity> updateDataEntityList, PaasFormDataEntity paasFormDataEntity, List<String> supplierIdArr, List<String> supplierNameArr) {
        if (Objects.nonNull(supplierIdArr) && supplierIdArr.contains(supplierId.toString())) {
            supplierIdArr.remove(supplierId.toString());
            supplierNameArr.remove(supplierName);
            JSONObject data = new JSONObject();
            data.put(ProductEnum.SUPPLIER.getAttr(), supplierIdArr);
            data.put(ProductEnum.SUPPLIER_LINK_TEXT.getAttr(), supplierNameArr);
            updateDataEntityList.add(ExplainUtil.getUpdateData(paasFormDataEntity.getId(), data, corpid));
        }
    }
}
